using Game.Networking;
using Game.Networking.Server;
using Game.UI;
using MemoryPack;
using NaughtyAttributes;
using SMGCore;
using UnityEngine;

namespace Game {
	public sealed partial class Missile : WorldEntity<MissileState> {
		public override EntityType EntityType => EntityType.Projectile;

		public ShipPhysics Physics;
		public GameObject  ExplosionEffect;
		public Collider    Collider;
		public int         Damage = 50;
		public float       ExplosionRadius = 4f;
		public float	   DummyTime = 1f;
		public float       MaxLifeTime = 12f;
		public uint OwnerId;

		TeamType _team;
		uint _target;
		float _lifeTime;
		
		[MemoryPackIgnore]
		public uint Target {
			get => _target;
			set => _target = value;
		}

		[MemoryPackIgnore]
		[ShowNativeProperty]
		public TeamType Team {
			get {
				return _team;
			}
			set {
				_team = value;
				GetComponentInChildren<ColoredTrail>()?.SetMaterial(value);
			}
		}

		public override void Create() {
			base.Create();
			if ( !IsServer ) {
				Physics.enabled = false;
				Physics.Enabled = false;
			} else {
				Physics.Thrust = 1f;
				Physics.ThrustAutopilot = false;
				Physics.Enabled = false;
				if ( _lifeTime > DummyTime) {
					Collider.enabled= true;
				} else {
					Collider.enabled= false;
				}
			}
		}

		public override void Tick(float currentTime, float deltaTime) {
			base.Tick(currentTime, deltaTime);
			if ( !IsServer || !IsEntityAlive ) {
				return;
			}
			_lifeTime += deltaTime;
			if ( _lifeTime > MaxLifeTime ) {
				S_CallRPC_Explode(true);
				DestroyEntity();
				return;
			}
			if ( _lifeTime < DummyTime || _target == 0 ) {//поначалу тупо летим на полном ходу вперед
				return;
			}
			var e = ServerEntityController.Instance.GetEntityById( _target );
			if ( e == null || !e.IsEntityAlive ) {
				return;
			}
			GuidanceUpdate(e);			
		}

		void GuidanceUpdate(Entity e) {
			var dist = Vector3.Distance(transform.position, e.transform.position);
			if ( dist < ExplosionRadius) {
				var rcv = e as IDamageReceiver;
				if ( rcv != null ) {
					rcv.ApplyDamage(new DamageDescription(OwnerId, Team, Damage, transform.position, Vector3.up));
				}
				S_CallRPC_Explode(true);
				DestroyEntity();
				return;

			}
			var rb = e.Rb;
			var entityVel = Vector3.zero;
			if ( rb ) {
				entityVel = rb.velocity;
			}
			var timeToFly = dist / Mathf.Max(Rb.velocity.magnitude, 1f); //Принимаем что мы летим точно к цели
			var extrapolatedPos = e.transform.position + entityVel * timeToFly;
			Physics.MoveTarget = extrapolatedPos; //ракета целится не прямо в текущую позицию цели, а в линейно экстраполированную точку, в которой цель будет при условии, что она движется равномерно по прямой
		}

		[ClientRPC(16)]
		void Explode() {
			var effect = Instantiate(ExplosionEffect);
			if ( !effect ) {
				return;
			}
			effect.transform.position = transform.position;
			var timer = effect.GetComponent<TimedDestroy>();
			if ( timer ) {
				timer.Activate(5f);
			}
			gameObject.SetActive(false);
		}

		protected override string CreateSummary() {
			return $"type:missile,team:{Team},target:{_target}"; ;
		}

		public override void ApplyFullState(EntityState state) {
			base.ApplyFullState(state);
			var cast = (MissileState)state;
			if ( cast == null ) {
				return;
			}
			_team = cast.Team;
			_target = cast.TargetEntityId;
			_lifeTime = cast.LifeTime;
			OwnerId = cast.OwnerId;
		}

		protected override MissileState SaveInternal() {
			var s = base.SaveInternal();
			s.Team = Team;
			s.TargetEntityId = _target;
			s.LifeTime = _lifeTime;
			s.OwnerId = OwnerId;
			return s;
		}

		private void OnCollisionEnter(Collision collision) {
			if ( !IsServer || !IsEntityAlive) {
				return;
			}
			S_CallRPC_Explode(true);
			DestroyEntity();
		}
	}

	[MemoryPackable]
	public partial class MissileState : WorldEntityState {
		public TeamType Team;
		public uint TargetEntityId;
		public uint OwnerId;
		public float LifeTime;
	}
}
